// 双向链表

(function () {
  let ElementNode = null;

  const _headNode = Symbol('_headNode')
  class DoubleList {
    constructor() {
      Object.defineProperties(this, {
        [_headNode]: {
          value: null,
          writable: true,
          enumerable: false
        }
      })
    }
    // 插入节点的方法
    insert(element, index = 0) {
      if (this.len() === 0) {
        let node = new ElementNode({ prev: null, next: null, element })
        this[_headNode] = node; // 默认插入的第一个节点是头节点
        return node;
      }
      if (index < 0 || index > this.len()) { // 该节点不存在，index有错误
        throw new Error('index 有误')
      }
      let findNode = this.find(index);
      // 插入后变成头节点
      if (index === 0) {
        let node = new ElementNode({ prev: null, element, next: findNode }) //创建一个新的节点，让该节点的后继指向查找到的节点
        findNode.setPrev(node); // 让查找到的节点的前驱指向新插入的节点
        this[_headNode] = node; // 更改头节点的指向
        return node;
      }
      // 插入后变成尾节点
      if (index === this.len()) {
        findNode = this.find(index - 1)
        let node = new ElementNode({ prev: findNode, element, next: null }) //创建一个新的节点，让该节点的后继指向查找到的节点
        findNode.setNext(node); // 让查找到的节点的后继指向新插入的节点
        return node;
      }
      // 插入后变成中间节点
      let prevNode = findNode.getPrev();
      let nextNode = findNode;
      const node = new ElementNode({ element, prev: prevNode, next: nextNode })
      // 让prevNode的后继指向node
      prevNode.setNext(node)
      // 让nextNode的前驱指向node
      nextNode.setPrev(node);
      return node;
    }
    // 删除节点的方法
    remove(index) {
      if (index < 0 || index >= this.len()) {
        throw new Error('index error')
      }
      let findNode = this.find(index);
      if (index === 0) {
        let nextNode = findNode.getNext();
        findNode.setNext(null);
        if (nextNode) {
          nextNode.setPrev(null);
        }
        this[_headNode] = findNode;
        return true;
      }
      if (index === this.len() - 1) {
        let prevNode = findNode.getPrev();
        findNode.setPrev(null);
        prevNode.setNext(null);
        return true;
      }

      let prevNode = findNode.getPrev();
      let nextNode = findNode.getNext();
      findNode.setPrev(null)
      findNode.setNext(null)
      prevNode.setNext(nextNode)
      nextNode.setPrev(prevNode);
      return true;
    }
    // 获取链表的长度
    len() {
      if (!this[_headNode]) {
        return 0;
      }
      let sum = 0;
      let n = this[_headNode];
      while (n) {
        n = n.getNext();
        sum += 1;
      }
      return sum;
    }
    // 根据索引取查找节点
    find(index) {
      if (!this[_headNode]) {
        return null;
      }
      let n = this[_headNode];
      let sum = 0;
      while (n && index !== sum) {
        n = n.getNext();
        sum += 1;
      }
      return n;
    }
    // 查看所有的元素
    toArray() {

      if (!this[_headNode]) {
        return [];
      }
      let arr = [this[_headNode]];
      let n = this[_headNode].getNext();
      while (n) {
        arr.push(n);
        n = n.getNext();
      }
      return arr;
    }
    // 查看headNode
    getHead() {
      return this[_headNode];
    }
  }
  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined' && typeof exports !== 'undefined') {
    ElementNode = require('./elementNode');
    module.exports = DoubleList;
  } else if (typeof window) {
    ElementNode = window.ElementNode;
    window.DoubleList = DoubleList;
  }
})()